package com.zhouyipeng;

import java.util.*;

/**
 * 房贷计算器
 * <p>
 * 搜狗金融的房贷计算器可以验证当前程序计算结果
 * <p>
 * domain：https://jinrong.sogou.com/calculator#
 *
 * @author zhouyipeng
 * @since 2021-06-23
 */
public class HouseLoanTest0623 {


    public static void main(String[] args) {

        double principal = 328580.00D;
        int months = 10 * 12;
        double rate = 4.9;


        Map<String, String> map = calculateEqualPrincipal(principal, months, rate);

        Set<Map.Entry<String, String>> entrySet = map.entrySet();

        System.out.println("等额本金 : ");
        entrySet.forEach(entry -> {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        });

        System.out.println("==================================================");

        System.out.println("等额本息 : ");

        Map<String, String> retMap = calculateEqualPrincipalAndInterest(principal, months, 0, rate);
        Set<Map.Entry<String, String>> entries = retMap.entrySet();
        entries.forEach(entry -> {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        });
    }

    /**
     * 计算等额本金还款
     *
     * @param principal 贷款总额
     * @param months    贷款期限
     * @param rate      贷款利率
     * @return
     */
    public static Map<String, String> calculateEqualPrincipal(double principal, int months, double rate) {
        ArrayList<String> data = new ArrayList<String>();

        Map<String, String> retMap = new HashMap<>(6);
        //月利率
        double monthRate = rate / (100 * 12);

        //每月还款本金
        double prePrincipal = principal / months;

        //第一个月还款金额
        double firstMonth = prePrincipal + principal * monthRate;

        //每月利息递减
        double decreaseMonth = prePrincipal * monthRate;

        //还款总利息
        double interest = (months + 1) * principal * monthRate / 2;

        //还款总额
        double totalMoney = principal + interest;

        //还款总额
        data.add(String.valueOf(totalMoney));
        retMap.put("还款总额", String.valueOf(totalMoney));

        //贷款总额
        data.add(String.valueOf(principal));
        retMap.put("贷款总额", String.valueOf(principal));

        //还款总利息
        data.add(String.valueOf(interest));
        retMap.put("还款总利息", String.valueOf(interest));

        //首月还款金额
        data.add(String.valueOf(firstMonth));
        retMap.put("首月还款金额", String.valueOf(firstMonth));

        //每月递减利息
        data.add(String.valueOf(decreaseMonth));
        retMap.put("每月递减利息", String.valueOf(decreaseMonth));

        //还款期限
        data.add(String.valueOf(months));
        retMap.put("还款期限", String.valueOf(months));


        return retMap;
    }

    /**
     * 一次性提前还款计算（等额本息）
     *
     * @param principal 贷款总额
     * @param months    贷款期限
     * @param payTimes  已还次数
     * @param rate      贷款利率
     * @return
     */
    public static Map<String, String> calculateEqualPrincipalAndInterest(double principal, int months, int payTimes, double rate) {

        Map<String, String> retMap = new HashMap<>(9);

        //月利率
        double monthRate = rate / (100 * 12);

        //每月还款金额
        double preLoan = (principal * monthRate * Math.pow((1 + monthRate), months)) / (Math.pow((1 + monthRate), months) - 1);

        //还款总额
        double totalMoney = preLoan * months;

        //还款总利息
        double interest = totalMoney - principal;

        //n个月后欠银行的钱
        double leftLoan = principal * Math.pow(1 + monthRate, payTimes) - preLoan * (Math.pow(1 + monthRate, payTimes) - 1) / monthRate;

        //已还本金
        double payLoan = principal - leftLoan;

        //已还总金额
        double payTotal = preLoan * payTimes;

        //已还利息
        double payInterest = payTotal - payLoan;

        //剩余一次还清
        double totalPayAhead = leftLoan * (1 + monthRate);

        //节省利息
        double saveInterest = totalMoney - payTotal - totalPayAhead;

        //原还款总额
        retMap.put("原还款总额", String.valueOf(totalMoney));

        //贷款总额
        retMap.put("贷款总额", String.valueOf(principal));

        //原还款总利息
        retMap.put("原还款总利息", String.valueOf(interest));

        //原还每月还款金额
        retMap.put("原还每月还款金额", String.valueOf(preLoan));

        //已还总金额
        retMap.put("已还总金额", String.valueOf(payTotal));

        //已还本金
        retMap.put("已还本金", String.valueOf(payLoan));

        //已还利息
        retMap.put("已还利息", String.valueOf(payInterest));

        //一次还清支付金额
        retMap.put("一次还清支付金额", String.valueOf(totalPayAhead));

        //节省利息
        retMap.put("节省利息", String.valueOf(saveInterest));

        return retMap;
    }

}
